package com.zhi.inisyccalllog;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import androidx.core.content.ContextCompat;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.zhi.inisyccalllog.logger.ASLogger;
import com.zhi.inisyccalllog.services.ASCallLogInfo;
import com.zhi.inisyccalllog.services.ASNetParams;
import com.zhi.inisyccalllog.util.ASGeneralUtil;
import com.zhi.inisyccalllog.util.ASNetworkUtil;
import com.zhi.inisyccalllog.util.ASUtil;

import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

@SuppressLint("StaticFieldLeak")
public class ASCallLogManager {
    public Context mContext;

    public static String mCalogZipString;

    private CallLogFetchingListener mCallLogFetchingListener;

    private SharedPreferences msharedPreferences;

    private static final ASCallLogManager instance = new ASCallLogManager();

    public static ASCallLogManager getInstance() {
        return instance;
    }

    public ASCallLogManager() {
    }

    public ASCallLogManager init(Context paramContext) {
        this.mContext = paramContext;
        this.msharedPreferences = paramContext.getSharedPreferences("ascalllogmanager", Context.MODE_PRIVATE);
        return this;
    }

    public void setCommonParams(String gversion,
                                String gsysLoginName,
                                String gadvertId,
                                String gtoken,
                                String gloginId) {

        String gip = ASNetworkUtil.getIPAddress(mContext);
        String gmac = ASNetworkUtil.getMacAddress(mContext);
        String gandroidId = ASGeneralUtil.getAndroidID(mContext);

        ASCallLogBuilder.KEY_VERSION = gversion;
        ASCallLogBuilder.KEY_USER_NAME = gsysLoginName;
        ASCallLogBuilder.KEY_ADVERT_ID = gadvertId;
        ASCallLogBuilder.KEY_TOKEN = gtoken;
        ASCallLogBuilder.KEY_LOGIN_ID = gloginId;
        ASCallLogBuilder.KEY_IP = gip;
        ASCallLogBuilder.KEY_MAC = gmac;
        ASCallLogBuilder.KEY_ANDROID_ID = gandroidId;
    }


    public void sycData(String uploadUrl, String token, String borrowId, String type) {
        try {
            if (this.mContext == null) return;
//            if (TextUtils.isEmpty(uploadUrl)) return;
//            if (TextUtils.isEmpty(token)) return;

            String tempType = ASUtil.safeString(type);
            if (ASCallLogBuilder.TYPE_CALL_LOG.equalsIgnoreCase(tempType)) {
                if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this.mContext, Manifest.permission.READ_CALL_LOG)) {
                    //callLog
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        new Thread(new CallLogListRunable(uploadUrl, token, borrowId)).start();
                    }
                } else {
                    //no permissions
                    int RESULT_CODE_NO_PERMISSION = 2004;
                    postResutl(uploadUrl, false, RESULT_CODE_NO_PERMISSION, "获取通话记录列表出错：没有 READ_CALL_LOG 权限");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String getLastUpdateTime() {
        return ASUtil.safeString(this.msharedPreferences.getString(ASCallLogBuilder.KEY_FETCH_LAST_UPDATE_TIME, ""));
    }

    public void getCallLogZipString(CallLogFetchingListener callLogFetchingListener) {
        ASLogger.d(ASCallLogInfo.class.getSimpleName(), "getCallLogZipString: " );
        this.mCallLogFetchingListener = callLogFetchingListener;
        if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this.mContext, Manifest.permission.READ_CALL_LOG)) {
            //callLog
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                new Thread(new FetchCallLogZipStringRunable()).start();
            }
        } else {
            //no permissions
            if(callLogFetchingListener!=null){
                callLogFetchingListener.onFetchFail("NO READ_CALL_LOG PERMISSION");
            }
        }
    }

    @SuppressLint("ApplySharedPref")
    public void saveLastUpdateTime(boolean updateSuccess) {
        try {
            String curMillis = updateSuccess ? String.valueOf(System.currentTimeMillis()) : "";
            SharedPreferences.Editor editor = msharedPreferences.edit();
            editor.putString(ASCallLogBuilder.KEY_FETCH_LAST_UPDATE_TIME, curMillis);
            editor.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void cleanCallLogZipCached() {
        //mCalogZipString = "";
    }

    @SuppressLint("ApplySharedPref")
    public static void clean() {
        try {
            mCalogZipString = "";
            if (getInstance().msharedPreferences != null) {
                SharedPreferences.Editor editor = getInstance().msharedPreferences.edit();
                editor.putString(ASCallLogBuilder.TYPE_CALL_LOG, "");
                editor.commit();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @SuppressLint("ApplySharedPref")
    public static void testClean(){
        try {
            mCalogZipString = "";
            if (getInstance().msharedPreferences != null) {
                SharedPreferences.Editor editor = getInstance().msharedPreferences.edit();
                editor.putString(ASCallLogBuilder.KEY_FETCH_LAST_UPDATE_TIME, "");
                editor.commit();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public final String getReceiver() {
        String receiver = ASCallLogBuilder.AS_RECEIVER;
        try {
            receiver = (this.mContext.getPackageName() + ASCallLogBuilder.AS_RECEIVER);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return receiver;
    }

    public final void postResutl(String type, boolean success, int resultCode, String resultMsg) {
        String state = (success ? "YES" : "NO");
        this.saveLastUpdateTime(success);
        Intent intent = new Intent();
        intent.setAction(ASCallLogBuilder.AS_ACTION);
        intent.putExtra("SyncedData", "");
        intent.putExtra("SyncedMsg", resultMsg);
        intent.putExtra("SyncedState", state);
        intent.putExtra("SyncedType", type);
        intent.putExtra("SyncedCode", String.valueOf(resultCode));
        intent.putExtra("SyncedBorrowId", ASUtil.safeString(""));
        intent.setPackage(this.mContext.getPackageName());
        intent.setComponent(new ComponentName(this.mContext.getPackageName(), getReceiver()));
        this.mContext.sendBroadcast(intent);
    }

    public final void postData(String url, String type, String body) {
        String dirUrl = ASUtil.safeString(url);
        ASLogger.d(getClass().getSimpleName(), dirUrl + "\n" + body);

        if (TextUtils.isEmpty(dirUrl)) {
            postResutl(type, false, -1, "Url is empty");
            return;
        }
        HttpURLConnection httpURLConnection = null;
        try {
            httpURLConnection = ((HttpURLConnection) new URL(dirUrl).openConnection());
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            httpURLConnection.setUseCaches(false);
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
            httpURLConnection.setRequestProperty("Charset", "UTF-8");
            httpURLConnection.setRequestProperty("Content-Type", "application/json");
            httpURLConnection.setRequestProperty("Content-Length", (body.getBytes()).length + "");
            httpURLConnection.setReadTimeout(180000);
            httpURLConnection.setConnectTimeout(120000);
            httpURLConnection.getOutputStream().write(body.getBytes());
            httpURLConnection.getOutputStream().flush();
            httpURLConnection.getOutputStream().close();

            if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                InputStream inputStream = httpURLConnection.getInputStream();
                byte[] arrayOfByte = new byte[1024];
                int len;
                while ((len = inputStream.read(arrayOfByte)) != -1) {
                    byteArrayOutputStream.write(arrayOfByte, 0, len);
                }

                String mUtf8Char = "UTF-8";
                String result = new String(byteArrayOutputStream.toByteArray(), mUtf8Char);
                JSONObject resultObject = new JSONObject(result);
                byteArrayOutputStream.close();
                ASLogger.d(getClass().getSimpleName(), "postData: " + resultObject);

                String msg = resultObject.getString("msg");
                String codeStr = resultObject.getString("code");
                int code = Integer.parseInt(codeStr);
                postResutl(type, (code == 200 || code == 0), code, msg);

            } else {
                postResutl(type, false, httpURLConnection.getResponseCode(), httpURLConnection.getResponseMessage());
            }

        } catch (Exception e) {
            e.printStackTrace();
            postResutl(type, false, -1, e.getMessage());
        } finally {
            if (httpURLConnection != null) {
                try {
                    //主动关闭inputStream, 这里不需要进行判空操作
                    httpURLConnection.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                httpURLConnection.disconnect();
            }
        }
    }

    class CallLogListRunable implements Runnable {
        private final String mUploadUrl;
        public String mBorrowId;
        public String mToken;

        public CallLogListRunable(String uploadUrl, String token, String borrowId) {
            this.mUploadUrl = uploadUrl;
            this.mBorrowId = borrowId;
            this.mToken = token;
        }

        @Override
        public void run() {
            try {

                ASLogger.d(ASCallLogInfo.class.getSimpleName(), "runCallLogListRunable: ");

                if (TextUtils.isEmpty(mCalogZipString)) {
                    ASLogger.d(ASCallLogInfo.class.getSimpleName(), "mCalogZipString: Empty");
                    mCalogZipString = ASCallLogInfo.getListZipString(ASCallLogManager.getInstance().mContext);
                }
                String infoBeans = mCalogZipString;
                ASNetParams netParams = new ASNetParams();
                netParams.setCallLogListGzip(infoBeans);
                String result = new Gson().toJson(netParams).trim();
                ASLogger.d(getClass().getSimpleName(), "run: " + ASCallLogBuilder.TYPE_CALL_LOG + "：" + result);
                if (ASCallLogBuilder.B_IS_MOCK) {
                    postResutl(ASCallLogBuilder.TYPE_CALL_LOG, true, 0, "success");
                    return;
                }
                postData(ASCallLogBuilder.B_SERVER_HOST + ASCallLogBuilder.PATH_CALL_LOG, ASCallLogBuilder.TYPE_CALL_LOG, result);
            } catch (Exception e) {
                postResutl(ASCallLogBuilder.TYPE_CALL_LOG, false, 1003, "获取通话记录列表出错");
            }
        }
    }

    class FetchCallLogZipStringRunable implements Runnable {

        @Override
        public void run() {
            try {
                mCalogZipString = ASCallLogInfo.getListZipString(ASCallLogManager.getInstance().mContext);
                if (Looper.myLooper() != Looper.getMainLooper()) {
                    Handler mainThread = new Handler(Looper.getMainLooper());
                    mainThread.post(new Runnable() {
                        @Override
                        public void run() {
                            ASLogger.d(ASCallLogInfo.class.getSimpleName(), "FetchCallLogZipStringRunable: Success" );

                            if (mCallLogFetchingListener != null) {
                                mCallLogFetchingListener.onFetchSuccess();
                            }
                        }
                    });
                } else {
                    ASLogger.d(ASCallLogInfo.class.getSimpleName(), "FetchCallLogZipStringRunable: Fail" );

                    if (mCallLogFetchingListener != null) {
                        mCallLogFetchingListener.onFetchSuccess();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public interface CallLogFetchingListener {
        void onFetchSuccess();

        void onFetchFail(String err);
    }
}
